/*
 * LinkedList.h
 *
 *  Created on: Jun 30, 2012
 *      Author: nam20485
 */

#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_

// test this too

template <class T>
class LinkedList
{
public:
	LinkedList();
	virtual ~LinkedList();

	class Node
	{
	public:
		Node(const T& value)
			: _pNext(0),
			  _value(value)
		{}

		~Node()
		{
			if (_pNext)
			{
				// delete the next node
				delete _pNext;
				_pNext = 0;
			}
		}

		const T& Value() const { return _value; }
		//const Node* Next() const { return _pNext; }
		//void SetNext(const Node* n)	{ _pNext = n; }

		Node* _pNext;

	protected:
		const T& _value;

		Node()	{ /* disallow */ }
	};

	void Add(const T& value);
	unsigned int Count() const;
	const Node* Head() const;
	bool IsEmpty() const;
	//const Node* GetNext(Node* p);
	//const Node* GetHead() const;

	void Clear();

protected:
	Node* _pHead;

	// remove and delete all linked nodes
	//void Clear();
};

//
//	apparently templat member fxns must be implemented in
//	same file as template declaration
//

template<class T>
inline LinkedList<T>::LinkedList()
	: _pHead(0)
{
}

template<class T>
inline LinkedList<T>::~LinkedList()
{
	Clear();
}

template<class T>
inline bool LinkedList<T>::IsEmpty() const
{
	return (_pHead == 0);
}

template<class T>
inline void LinkedList<T>::Clear()
{
	// delete the first node, will cascade the deletes
	if (_pHead)
	{
		delete _pHead;
		_pHead = 0;
	}
}

template<class T>
inline const typename LinkedList<T>::Node* LinkedList<T>::Head() const
{
	return _pHead;
}

template<class T>
inline void LinkedList<T>::Add(const T& value)
{
	Node* pNew = new Node(value);
	if (_pHead)
	{
		// find last node in link
		Node* pLast = _pHead;
		while (pLast->_pNext)
		{
			pLast = pLast->_pNext;
		}

		// add new node to end
		pLast->_pNext = pNew;
	}
	else
	{
		_pHead = pNew;
	}
}

template<class T>
inline unsigned int LinkedList<T>::Count() const
{
	unsigned int count  = 0;

	const Node* p = _pHead;
	while (p)
	{
		count++;
		if (p->Next())
		{
			p = p->Next();
		}
	}

	return count;
}

//template<class T>
//inline void LinkedList<T>::DeleteList()
//{
//	Node* p = _pHead;
//	while (p)
//	{
//		Node* pNext = p->pNext;
//		delete p;
//		p = pNext;
//	}
//}


#endif /* LINKEDLIST_H_ */
